package com.rtsapp.server.gamelog.analyze.stat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by liwang on 17-1-16.
 * <p>
 * 汇率管理类
 * <p>
 * 用于获取实时汇率或者保存历史汇率等
 */
public class ExchangeRateMgr {

    private static final ExchangeRateMgr instance = new ExchangeRateMgr( );

    private ExchangeRateMgr( ) {

    }

    public static final ExchangeRateMgr getInstance( ) {
        return instance;
    }


    // 人民币通用标识
    private static final String CNY = "CNY";
    // 日元通用标识
    private static final String JPY = "JPY";
    private static final String JPY_URLEncoder = "%E6%97%A5%E5%85%83";
    // 韩元通用表示
    private static final String KRW = "KRW";
    private static final String KRW_URLEncoder = "%E9%9F%A9%E5%85%83";
    // 台币
    private static final String TWD = "TWD";
    private static final String TWD_URLEncoder = "%E5%8F%B0%E5%B8%81";
    // 美元
    private static final String USD = "USD";
    private static final String USD_URLEncoder = "%E7%BE%8E%E5%85%83";


    private static final String URL1 = "https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=";
    //            + moneyNum
//            + URLEncoder.encode( currency, "UTF-8" )
    private static final String URL2 = "%E7%AD%89%E4%BA%8E%E5%A4%9A%E5%B0%91%E4%BA%BA%E6%B0%91%E5%B8%81&co=&resource_id=6017&t=";
    //            + time_MS
    private static final String URL3 = "&ie=utf8&oe=gbk&cb=op_aladdin_callback&format=json&tn=baidu&cb=jQuery110205721266000885261_1484886101015&_=";
//            +time_MS;


    // 保存最近一次计算时的汇率.   key:需要转换为人民币的货币类型, value:汇率 (1目标货币兑换成人民币的数值)
    private static final ConcurrentMap< String, Float > exchangeRateMap = new ConcurrentHashMap<>( );

    public String sendGet( String URL ) {
        String result = "";
        BufferedReader in = null;
        try {
            // 打开和URL之间的连接
            URLConnection connection = new URL( URL ).openConnection( );
            // 设置通用的请求属性
            connection.setRequestProperty( "accept", "*/*" );
//            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect( );
            // 获取所有响应头字段
            Map< String, List< String > > map = connection.getHeaderFields( );
            // 遍历所有的响应头字段
            for ( String key : map.keySet( ) ) {
//                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader( new InputStreamReader( connection.getInputStream( ), "GBK" ) );
            String line;
            while ( ( line = in.readLine( ) ) != null ) {
                result += line;
            }
        } catch ( Exception e ) {
            System.out.println( "发送GET请求出现异常！" + e );
            e.printStackTrace( );
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if ( in != null ) {
                    in.close( );
                }
            } catch ( Exception e2 ) {
                e2.printStackTrace( );
            }
        }

        return result;
    }


    /**
     * 从转换结果中提取人民币数值, 并且保存实时汇率
     */
    private float getExchangeResult( String responseStr, String currency ) {

        // 从响应body中取出json字符串
        String jsonStr = responseStr.split( "\\(" )[ 1 ].split( "\\)" )[ 0 ];

        JSONObject resultDataJson = JSON.parseObject( JSON.parseObject( jsonStr ).getJSONArray( "data" ).get( 0 ).toString( ) );

        float exchangeRate = Float.parseFloat( resultDataJson.getString( "content1" ).split( "=" )[ 1 ].split( "人民币元" )[ 0 ] );
        if ( exchangeRate > 0 ) {
            System.out.println( "1 " + currency + " = " + exchangeRate + " CNY" );
            exchangeRateMap.put( currency, exchangeRate );
        }

        float jpn = Float.parseFloat( resultDataJson.getString( "number2" ) );

        return jpn >= 0 ? jpn : 0;
    }

    /**
     * 在线获取实时汇率
     * 如果在线获取出现错误, 取最近一次保存的汇率
     *
     * @param currency
     * @return
     */
    public Float getRealTimeExchangeRate( String currency, long time_MS ) {
        if ( CNY.equals( currency ) ) {
            return 1F;
        }

        String url = getUrlByCurrency( currency, 1, time_MS );
        String responseStr = sendGet( url );

        Float exchangeRate = 0f;
        try {
            // 从响应body中取出json字符串
            String jsonStr = responseStr.split( "\\(" )[ 1 ].split( "\\)" )[ 0 ];

            JSONObject resultDataJson = JSON.parseObject( JSON.parseObject( jsonStr ).getJSONArray( "data" ).get( 0 ).toString( ) );

            exchangeRate = Float.parseFloat( resultDataJson.getString( "content1" ).split( "=" )[ 1 ].split( "人民币元" )[ 0 ] );

        } catch ( Throwable e ) {
            System.out.println( "\n在线获取汇率时发生未知错误!" );
            e.printStackTrace( );
        }


        if ( exchangeRate > 0 ) {
            System.out.println( "1 " + currency + " = " + exchangeRate + " CNY" );
            exchangeRateMap.put( currency, exchangeRate );
        } else {
            System.out.println( "\n在线获取汇率失败! 将使用上一次正确获取的汇率!" );
            exchangeRate = exchangeRateMap.get( currency );
        }

        if ( exchangeRate == null || exchangeRate <= 0 ) {
            System.out.println( currency + " 未能正确获取到汇率!" );

            // 在线获取汇率异常, 发送邮件
            sendExchangeRateErrorMail( currency, url );
        }

        return exchangeRate;
    }


    /**
     * 拼接汇率换算URL
     *
     * @param currency 货币类型
     * @param moneyNum 货币数量
     * @return 请求URL
     */
    private String getUrlByCurrency( String currency, float moneyNum, long time_MS ) {

        String url = URL1 + moneyNum;

        switch ( currency ) {

            case JPY: {
                url += JPY_URLEncoder;
                break;
            }

            case KRW: {
                url += KRW_URLEncoder;
                break;
            }

            case TWD: {
                url += TWD_URLEncoder;
                break;
            }

            case USD: {
                url += USD_URLEncoder;
                break;
            }

            default: {
                return null;
            }
        }

        return url + URL2 + time_MS + URL3 + time_MS;
    }

    /**
     * 将货币转换为人民币
     *
     * @param currency
     * @return
     */
    public float exchangeToCNY( String currency, float moneyNum, long time_MS ) {
        // 人民币不需要换算
        if ( CNY.equals( currency ) ) {
            return moneyNum;
        }

        // 发送汇率换算请求
        String resultData = sendGet( getUrlByCurrency( currency, moneyNum, time_MS ) );

        // 将汇率换算结果的人民币数值提取出来
        try {
            return getExchangeResult( resultData, currency );
        } catch ( Throwable e ) {
            System.out.println( "发生未知错误!" );
            e.printStackTrace( );
        }


        // 容错: 在线汇率换算发生错误, 使用最近一次保存的汇率进行计算
        System.out.println( "在线汇率换算发生错误, 使用最近一次保存的汇率进行计算" );
        Float exchangeRate = exchangeRateMap.get( currency );
        if ( exchangeRate == null || exchangeRate <= 0 ) {
            System.out.println( currency + "转换CNY的汇率未找到!" );
            return -1;
        }

        return moneyNum * exchangeRate;
    }


    /**
     * 在线获取汇率失败后, 发送提醒邮件
     */
    private void sendExchangeRateErrorMail( String currency, String url ) {
        MailUtils.getInstance( ).sendMail( "rtsapp收入统计异常提醒", "在线获取汇率失败!    \n请检查代码!    \n货币类型: " + currency + "    \nurl: " + url );
    }
}
